package modeller.databasedesignmodel.transaction;

import exceptions.SQLQueryNotInProceduralStatementException;
import modeller.databasedesignmodel.servicedemand.transaction.proceduralstatement.IProceduralStatementServiceDemandCalculator;
import modeller.databasedesignmodel.servicedemand.IServiceDemand;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Created by:  Jason Ye
 * Date:        27/02/2012
 * Time:        15:12
 */
public class SQLQuerySequence implements IProceduralStatement,Serializable {

    private LinkedList<SQLQuery> statementSequence;

    public SQLQuerySequence() {
        this.statementSequence = new LinkedList<SQLQuery>();
    }

    /**
     * appends a query onto the end of the existing sequence
     *
     * @param newQuery
     */
    public void addSQLStatement(SQLQuery newQuery) {
        statementSequence.add(newQuery);
    }

    /**
     * Inserts an SQL query into the statement sequence given a preceding query
     *
     * @param newQuery
     * @param precedingQuery
     * @throws SQLQueryNotInProceduralStatementException
     *
     */
    public void addSQLStatement(SQLQuery newQuery, SQLQuery precedingQuery) throws SQLQueryNotInProceduralStatementException {

        // insert as getFirst SQLquery in sequence
        if (precedingQuery == null) {
            statementSequence.add(0, newQuery);
        } else if (!statementSequence.contains(precedingQuery)) {
            //invalid reference to a non existing query
            throw new SQLQueryNotInProceduralStatementException();
        } else {
            //insert in middle of sequence
            int insertAfterThisIndex = statementSequence.indexOf(precedingQuery);
            statementSequence.add(insertAfterThisIndex + 1, newQuery);
        }
    }

    /**
     * remove a specific query from the sequence
     *
     * @param toRemove
     */
    public void removeSQLStatement(SQLQuery toRemove) {
        statementSequence.remove(toRemove);
    }

    /**
     * remove a query at a specific index
     *
     * @param toRemove
     */
    public void removeSQLStatement(int toRemove) {
        statementSequence.remove(toRemove);
    }

    /**
     * clear out the statement list
     */
    public void emptyAllStatements() {
        statementSequence.clear();
    }

    @Override
    public String myToString() {

        StringBuffer buf = new StringBuffer();
        buf.append("SQL Statement Sequence with " + statementSequence.size() + " SQL statements:");

        Iterator<SQLQuery> it = statementSequence.listIterator();
        while (it.hasNext()) {
            buf.append("\n" + it.next().myToString() + "\n");
        }

        buf.append("End of SQL Statement sequence");

        return buf.toString();
    }

    public LinkedList<SQLQuery> getStatementSequence() {
        return statementSequence;
    }



    @Override
    public IServiceDemand acceptCalculation(IProceduralStatementServiceDemandCalculator visitor) {
        return visitor.calculate(this);
    }

}
